package com.blog.cloud.auth.oauth.request;

import com.alibaba.fastjson.JSONObject;
import com.blog.cloud.auth.oauth.cache.AuthDefaultSource;
import com.blog.cloud.auth.oauth.cache.AuthStateCache;
import com.blog.cloud.auth.oauth.config.AuthConfig;
import com.blog.cloud.auth.oauth.enums.AuthUserGender;
import com.blog.cloud.auth.oauth.exception.AuthException;
import com.blog.cloud.auth.oauth.model.AuthCallback;
import com.blog.cloud.auth.oauth.model.AuthToken;
import com.blog.cloud.auth.oauth.model.AuthUser;
import com.xkcoding.http.support.HttpHeader;
import me.zhyd.oauth.utils.AuthScopeUtils;
import me.zhyd.oauth.utils.GlobalAuthUtils;
import me.zhyd.oauth.utils.HttpUtils;
import me.zhyd.oauth.utils.UrlBuilder;

import java.util.Map;

public class AuthGithubRequest extends AuthDefaultRequest {
    public AuthGithubRequest(AuthConfig config) {
        super(config, AuthDefaultSource.GITHUB);
    }

    public AuthGithubRequest(AuthConfig config, AuthStateCache authStateCache) {
        super(config, AuthDefaultSource.GITHUB, authStateCache);
    }

    @Override
    protected AuthToken getAccessToken(AuthCallback authCallback) {
        String response = this.doPostAuthorizationCode(authCallback.getCode());
        Map<String, String> res = GlobalAuthUtils.parseStringToMap(response);
        this.checkResponse(res.containsKey("error"), (String)res.get("error_description"));
        return AuthToken.builder()
                .accessToken((String)res.get("access_token"))
                .scope((String)res.get("scope"))
                .tokenType((String)res.get("token_type"))
                .build();
    }

    @Override
    protected AuthUser getUserInfo(AuthToken authToken) {
        HttpHeader header = new HttpHeader();
        header.add("Authorization", "token " + authToken.getAccessToken());
        String response = (new HttpUtils(this.config.getHttpConfig())).get(UrlBuilder.fromBaseUrl(this.source.userInfo()).build(), (Map)null, header, false);
        JSONObject object = JSONObject.parseObject(response);
        this.checkResponse(object.containsKey("error"), object.getString("error_description"));
        return AuthUser.builder()
                .rawUserInfo(object).uuid(object.getString("id"))
                .username(object.getString("login"))
                .avatar(object.getString("avatar_url"))
                .blog(object.getString("blog"))
                .nickname(object.getString("name"))
                .company(object.getString("company"))
                .location(object.getString("location"))
                .email(object.getString("email"))
                .remark(object.getString("bio"))
                .gender(AuthUserGender.UNKNOWN)
                .token(authToken)
                .source(this.source.toString())
                .build();
    }

    @Override
    public String authorize(String state) {
        return UrlBuilder.fromBaseUrl(super.authorize(state)).queryParam("scope", this.getScopes(" ", true, AuthScopeUtils.getDefaultScopes(AuthGithubScope.values()))).build();
    }

    private void checkResponse(boolean error, String errorDescription) {
        if (error) {
            throw new AuthException(errorDescription);
        }
    }

}
